package com.activenetwork.smlite.testcase;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.events.WebDriverEventListener;
import org.openqa.selenium.support.pagefactory.ElementLocatorFactory;
import org.openqa.selenium.support.pagefactory.FieldDecorator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeSuite;

import com.activenetwork.custom.XPageFactory;
import com.activenetwork.custom.uielement.decorate.XElementDecorator;
import com.activenetwork.custom.uielement.decorate.XElementLocatorFactory;
import com.activenetwork.custom.uielement.gson.IdentifierCollection;
import com.activenetwork.custom.webelement.decorate.WebElementDecorator;
import com.activenetwork.custom.webelement.decorate.WebElementLocatorFactory;
import com.activenetwork.listener.ImplicitlyWaitListener;
import com.activenetwork.schema.environment.EnvironmentType;
import com.activenetwork.smlite.business.LoginBusiness;
import com.activenetwork.smlite.page.generic.NexusProgressPageObjectListener;
import com.activenetwork.util.EnvContext;
import com.activenetwork.util.PageLoader;
import com.activenetwork.util.WebDriverFactory;
import com.activenetwork.util.jaxb.XMLBindHelper;
import com.activenetwork.util.verification.gson.FailurePoint;
import com.google.common.base.Charsets;
import com.google.common.io.Resources;
import com.google.gson.Gson;


public class BaseCase {
	private Logger logger = LoggerFactory.getLogger(BaseCase.class);
	
	protected static EnvironmentType env; // all threads share one instance
	protected LoginBusiness loginBusiness; // replicate instance of login business
	protected WebDriver webDriver; // replicate instance for each thread
	
	
	@BeforeSuite(alwaysRun = true)
	public void updateJsonLookup() throws IOException{
		// InJson lookup initialization
		Gson gson = new Gson();
		String json = Resources.toString(Resources.getResource("identifier.json"), Charsets.UTF_8);
		IdentifierCollection collection = gson.fromJson(json, IdentifierCollection.class);
		collection.updateXpathLookup();
		logger.info("@BeforeSuite updateJsonLookup succeeded");
	}
	
	
	@BeforeSuite(dependsOnMethods={"updateJsonLookup"},alwaysRun = true)
	public void environmentSetting() throws IOException{
		// Read properties to get which environment to run test
		ResourceBundle bundle = ResourceBundle.getBundle("RunWhichEnv");
		String whichEnv = bundle.getString("target_env");

		// Get target environment setting for running test
		XMLBindHelper helper = new XMLBindHelper("xml/" + whichEnv);
		env = helper.binding(EnvironmentType.class);
		
		logger.info("@BeforeSuite environmentSetting succeeded");
	}
	
	@BeforeSuite(dependsOnMethods={"environmentSetting"}, alwaysRun = true)
	public void pageLoaderPrecondition(){
		//ApplicationContext loaderContext = new ClassPathXmlApplicationContext("pageLoaderContext.xml");
		//XPageFactory factory1 = (XPageFactory)loaderContext.getBean("UIElementPageFactory");
		//XPageFactory factory2 = (XPageFactory)loaderContext.getBean("WebElementPageFactory");
		
		
		ElementLocatorFactory elementLocatorFactory1 = new XElementLocatorFactory();
		FieldDecorator decorator1 = new XElementDecorator(elementLocatorFactory1);
		XPageFactory factory1 = new XPageFactory(decorator1);
		
		ElementLocatorFactory elementLocatorFactory2 = new WebElementLocatorFactory();
		FieldDecorator decorator2 = new WebElementDecorator(elementLocatorFactory2);
		XPageFactory factory2 = new XPageFactory(decorator2);
		
		PageLoader.setPageFactory(factory1,factory2);
		PageLoader.setPageObjectListener(new NexusProgressPageObjectListener());	
		
		logger.info("@BeforeSuite pageLoaderPrecondition succeeded");
	}
	
	@BeforeClass(alwaysRun = true)
	public void webDriverPrecondition() {
		webDriver = EnvContext.webDriverTL.get();
		if(webDriver == null){
			// Get spring context
			// ApplicationContext driverContext = new ClassPathXmlApplicationContext("webDriverContext.xml");
			//driverContext.getBean("WebDriverFactory");// statically inject listener by spring
			
			List<WebDriverEventListener> list = new ArrayList<WebDriverEventListener>();
			list.add(new ImplicitlyWaitListener());
			WebDriverFactory.setList(list);
			
			WebDriverFactory.setUntrustedCertificateFlag(env.getTestEnvironment().isUntrustedCertificateIssuer());
			webDriver = WebDriverFactory.create(env.getBrowserSetting());
			EnvContext.webDriverTL.set(webDriver);
			logger.info("@BeforeClass webDriverPrecondition succeeded on thread " + Thread.currentThread().getName() + "-" + Thread.currentThread().getId());
		}else{
			logger.info("Found driver instance in thread local on thread " + Thread.currentThread().getName() + "-" + Thread.currentThread().getId());
		}
		
		
	}
	
	@BeforeClass(dependsOnMethods={"webDriverPrecondition"},alwaysRun = true)
	public void failurePointPrecondition(){
		EnvContext.failurePointTL.set(new ArrayList<FailurePoint>());
		logger.info("@BeforeClass failurePointPrecondition succeeded on thread " + Thread.currentThread().getName() + "-" + Thread.currentThread().getId());
	}
	
	@BeforeClass(dependsOnMethods={"failurePointPrecondition"},alwaysRun=true)
	public void loginBusinessPrecondition(){
		loginBusiness = new LoginBusiness(env.getTestEnvironment());
		logger.info("@BeforeClass loginBusinessPrecondition succeeded on thread " + Thread.currentThread().getName() + "-" + Thread.currentThread().getId());
	}
	
	/**
	 * It does not close the webdriver
	 */
	@AfterClass(alwaysRun = true)
	public void caseTeardown() {
		closeDown();
	}
	
	
	/**
	 * Called by specific end suite test and close the browser
	 */
	public void closeDown() {
		webDriver.quit();
		EnvContext.webDriverTL.set(null);
	}
	

}
